﻿using System;
using System.Diagnostics;
using Excel.Expressions.Compiler;
using Expressions.Compiler;
using Expressions.Compiler.Interfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Excel.Expressions.Interfaces;

namespace Tests
{

    /// <summary>
    ///This is a test class for TokenTest and is intended
    ///to contain all TokenTest Unit Tests
    ///</summary>
    [TestClass()]
    public class Test3__
    {

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        /// <summary>
        /// Declaration: http://msdn.microsoft.com/en-us/library/aa664812(VS.71).aspx
        /// </summary>
        /// <returns>IToken</returns>
        private Entity CreateGrammar()
        {
            Terminal cr = '\u000d';
            Terminal lf = '\u000a';
            Terminal ls = '\u2028';
            Terminal ps = '\u2029';

            Terminal sp = ' ';
            Terminal vt = '\u0008';
            Terminal ht = '\u0009';
            Terminal ff = '\u000c';

            Terminal t = 't';
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal input = "input";
            Nonterminal input_character = "input-character";
            Nonterminal input_sectionopt = "input-sectionopt";
            Nonterminal input_sections = "input-sections";
            Nonterminal input_section = "input-section";
            Nonterminal input_elements = "input-elements";
            Nonterminal input_element = "input-element";
            Nonterminal whitespace = "whitespace";
            Nonterminal comment = "comment";
            Nonterminal single_line_comment = "single-line-comment";
            Nonterminal token = "token";
            Nonterminal new_line = "new-line";
            Nonterminal new_line_character = "new-line-character";
            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";
            Nonterminal input_characters = "input-characters";

            input.Definition = new Rules
            {
                () => input_sections[true]
            };
            input_sections.Definition = new Rules
            {     
                () => input_section[false] + input_sections[false],
            };
            input_section.Definition = new Rules
            {
                () => input_elements[true] + new_line[false],
            };
            input_elements.Definition = new Rules
            {
                () => input_element[false] + input_elements[false]
            };
            input_element.Definition = new Rules
            {
                () => whitespace[false],
                () => comment[false],
                () => token[false]
            };
            new_line.Definition = new Rules
            {
                () => cr,
                () => lf,
                () => cr + lf,
                () => ls,
                () => ps
            };
            whitespace.Definition = new Rules
            {
                () => sp + whitespace[true],
                () => vt + whitespace[true],
                () => ht + whitespace[true],
                () => ff + whitespace[true]
            };
            comment.Definition = new Rules
            {
                () => single_line_comment[false],
                () => delimited_comment[false],
            };
            token.Definition = new Rules
            {
                () => t
            };
            single_line_comment.Definition = new Rules
            {
                () => "//" + input_characters[true]
            };
            input_characters.Definition = new Rules
            {
                () => input_character[false] + input_characters[false]
            };
            input_character.Definition = new Rules
            {
                () => !new_line_character[false]
            };
            new_line_character.Definition = new Rules
            {
                () => cr,
                () => lf,
                () => ls,
                () => ps
            };
            delimited_comment.Definition = new Rules
            {
                () => "/*" + delimited_comment_characters[true] + "*/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash[true],
            };
            return delimited_comment_characters;
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_1()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment_character = "delimited-comment-character";

            delimited_comment_character.Definition = new Rules
            {
                () => asterisk + slash,
            };

            delimited_comment_character.Initialize();
            delimited_comment_character.Validate();

            Entity target = delimited_comment_character;
            Parser input = @"*/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_2()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment_character = "delimited-comment-character";
            delimited_comment_character.Definition = new Rules
            {
                () => asterisk + slash,
            };

            delimited_comment_character.Initialize();
            delimited_comment_character.Validate();

            Entity target = delimited_comment_character;
            Parser input = @"*/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_3()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment_character = "delimited-comment-character";
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash,
            };

            Nonterminal grammar = "G";
            grammar.Definition = new Rules
            {
                () => delimited_comment_character[false]
            };

            Entity target = grammar;

            grammar.Initialize();
            grammar.Validate();

            Parser input = @"*/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == false;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_4()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment_character = "delimited-comment-character";
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash,
            };

            Nonterminal grammar = "G";
            grammar.Definition = new Rules
            {
                () => delimited_comment_character[false]
            };

            grammar.Initialize();
            grammar.Validate();

            Entity target = grammar;
            Parser input = @"/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }


        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_5()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => "/*" + delimited_comment_character[true] + asterisk + "/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false]// + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash,
            };

            Nonterminal grammar = "G";
            grammar.Definition = new Rules
            {
                () => delimited_comment[false] + Terminal.Null
            };

            grammar.Initialize();
            grammar.Validate();

            Entity target = grammar;
            Parser input = @"/**/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }


        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_6()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => "/" + asterisk + delimited_comment_character[true] + asterisk + "/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash,
            };

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Entity target = delimited_comment;
            Parser input = @"/**/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_7()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => "/" + asterisk + delimited_comment_characters[true] + asterisk + "/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash,
            };

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Entity target = delimited_comment;
            Parser input = @"/**/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_8()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => "/" + asterisk + delimited_comment_characters[true] + asterisk + "/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash,
            };

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Entity target = delimited_comment;
            Parser input = @"/* */";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_9()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => '/' + asterisk + delimited_comment_characters[true] + asterisk + "/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash[true]
            };

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Entity target = delimited_comment;

            Parser input = @"/***/";
            bool expected = true;
            bool actual;

            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }


        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_10()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => "/" + asterisk + delimited_comment_characters[true] + asterisk + "/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash[true]
            };

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Entity target = delimited_comment;
            Parser input = @"/**/";
            bool expected = true;
            bool actual;

            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }


        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_11()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => "/" + asterisk + delimited_comment_characters[true] + asterisk + "/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => !asterisk + delimited_comment_characters[true],
                () => asterisk + !slash[true] + delimited_comment_characters[true]
            };

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Entity target = delimited_comment;

            Parser input = @"/**/";
            bool expected = true;
            bool actual;

            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_12()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => "/*" + delimited_comment_characters[true] + "*/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash
            };
            Entity target = delimited_comment;
            Parser input = @"/***/";
            bool expected = true;
            bool actual;

            delimited_comment.Initialize();
            delimited_comment.Validate();

            actual = target.Parse(input) == false;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_13()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => "/*" + delimited_comment_characters[true] + "*/"
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash[true]
            };

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Entity target = delimited_comment;
            Parser input = @"/***/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }


        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_14()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => "/*" + delimited_comment_characters[true] + "*/" + Terminal.Null
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash[true]
            };

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Entity target = delimited_comment;
            Parser input = @"/** /*/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }


        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_15()
        {
            Terminal asterisk = "**";
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => slash + asterisk + delimited_comment_characters[true] + asterisk + slash + Terminal.Null
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash[true]
            };

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Entity target = delimited_comment;
            Parser input = @"/**** /**/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == true;
            Assert.AreEqual(expected, actual);
        }


        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_16()
        {
            Terminal asterisk = "**";
            Terminal slash = '/';

            Nonterminal delimited_comment = "delimited-comment";
            Nonterminal delimited_comment_character = "delimited-comment-character";
            Nonterminal delimited_comment_characters = "delimited-comment-characters";

            delimited_comment.Definition = new Rules
            {
                () => slash + asterisk + delimited_comment_characters[true] + asterisk + slash + Terminal.Null
            };
            delimited_comment_characters.Definition = new Rules
            {
                () => delimited_comment_character[false] + delimited_comment_characters[true]
            };
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash[true]
            };
            Entity target = delimited_comment;

            delimited_comment.Initialize();
            delimited_comment.Validate();

            Parser input = @"/****/**/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == false;
            Assert.AreEqual(expected, actual);
        }

        [TestMethod(), Conditional("DEBUG")]
        public void Test3_17()
        {
            // Forward declarations
            Nonterminal G = "_G";
            Nonterminal E = "_E";
            Nonterminal Eopt = "_E'";
            Nonterminal T = "_T";
            Nonterminal Topt = "_T'";
            Nonterminal F = "_F";
            Nonterminal N = "_N";
            Nonterminal real_literal = "_real-literal";
            Nonterminal exponent_part = "_exponent-part";
            Nonterminal sign = "_sign";
            Nonterminal real_type_suffix = "_real-type-suffix";
            Nonterminal decimal_digits = "_decimal-digits";
            Nonterminal decimal_digit = "_decimal-digit";

            Expression<CellExpression> Gexpr = "_G";
            Expression<CellExpression> Eexpr = "_E";
            Expression<CellExpression> Eoptexpr = "_E'";
            Expression<CellExpression> Texpr = "_T";
            Expression<CellExpression> Toptexpr = "_T'";
            Expression<CellExpression> Fexpr = "_F";
            Expression<CellExpression> Nexpr = "_N";
            Expression<CellExpression> real_literalexpr = "_real-literal";
            Expression<CellExpression> exponent_partexpr = "_exponent-part";
            Expression<CellExpression> signexpr = "_sign";
            Expression<CellExpression> real_type_suffixexpr = "_real-type-suffix";
            Expression<CellExpression> decimal_digitsexpr = "_decimal-digits";
            Expression<CellExpression> decimal_digitexpr = "_decimal-digit";

            real_literal.Definition = new Rules
            {
                () => sign[true] + decimal_digits[false] + '.' + decimal_digits[false] + exponent_part[true] + real_type_suffix[true],
                () => sign[true] + '.' + decimal_digits[false] + exponent_part[true] + real_type_suffix[true],
                () => sign[true] + decimal_digits[false] + exponent_part[false] + real_type_suffix[true],
                () => sign[true] + decimal_digits[false] + real_type_suffix[true]
            };

            exponent_part.Definition = new Rules
            {
                () => 'e' + sign[true] + decimal_digits[false],
                () => 'E' + sign[true] + decimal_digits[false]
            };

            sign.Definition = new Rules
            {
                () => '+',
                () => '-'
            };

            real_type_suffix.Definition = new Rules
            {
                () => 'F',
                () => 'f'
            };

            decimal_digits.Definition = new Rules
            {
                () => decimal_digit[false] + decimal_digits[true]
            };

            decimal_digit.Definition = new Rules
            {
                () => '0',
                () => '1',
                () => '2',
                () => '3',
                () => '4',
                () => '5',
                () => '6',
                () => '7',
                () => '8',
                () => '9'
            };

            G.Definition = new Rules 
            {
                () => E[false] + Terminal.Null
            };

            Gexpr.Eval = (a, b) => Eexpr[a, b[0]];

            E.Definition = new Rules
            {
                () => T[false] + Eopt[true]
            };

            Eexpr.Eval = (a, b) => Eoptexpr[Texpr[a, b[0]], b[1]];

            T.Definition = new Rules
            {
                () => F[false] + Topt[true]
            };

            Texpr.Eval = (a, b) => Toptexpr[Fexpr[a, b[0]], b[1]];

            F.Definition = new Rules
            {
                () => N[false],
                () => '(' + E[false] + ')'
            };

            Fexpr.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(N))
                {
                    return Nexpr[a, b[0]];
                }
                if (b[0].Context.Token.Equals('(') && b[1].Context.Token.Equals(E) && b[2].Context.Token.Equals(')'))
                {
                    return Eexpr[a, b[1]];
                }
                throw new NotSupportedException("Input token is not supported");
            };


            N.Definition = new Rules
            {
                () => real_literal[false],
            };

            Nexpr.Eval = (a, b) => real_literalexpr[a, b];

            real_literalexpr.Eval = (a, b) => new Number(b.Context.ToString());

            Eopt.Definition = new Rules
            {
                () => '+' + T[false] + Eopt[true],
                () => '-' + T[false] + Eopt[true]
            };

            Eoptexpr.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals('+'))
                {
                    return Eoptexpr[new Plus(a, Texpr[a, b[1]]), b[2]];
                }
                if (b[0].Context.Token.Equals('-'))
                {
                    return Eoptexpr[new Minus(a, Texpr[a, b[1]]), b[2]];
                }
                throw new NotSupportedException("Input token is not supported");
            };

            Topt.Definition = new Rules
            {
                () => '*' + F[false] + Topt[true],
                () => '/' + F[false] + Topt[true],
            };

            Toptexpr.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals('*'))
                {
                    return Toptexpr[new Mul(a, Fexpr[a, b[1]]), b[2]];
                }
                if (b[0].Context.Token.Equals('/'))
                {
                    return Toptexpr[new Div(a, Fexpr[a, b[1]]), b[2]];
                }
                throw new NotSupportedException("Input token is not supported");
            };

            G.Initialize();
            G.Validate();

            Entity target = G;

            Parser input = "6+((7-2)/5-9)*0.5-2+1";

            target.Parse(input);

            CellExpression result = Gexpr[input.Tree];

            bool expected = true;
            bool actual = result == 1;

            Assert.AreEqual(expected, actual);
        }

        [TestMethod(), Conditional("DEBUG")]
        public void Test3_18()
        {
            // Forward declarations
            Nonterminal G = "G";
            Nonterminal E = "E";
            Nonterminal Eopt = "E'";
            Nonterminal T = "T";
            Nonterminal Topt = "T'";
            Nonterminal F = "F";
            Nonterminal N = "N";
            Nonterminal real_literal = "real-literal";
            Nonterminal exponent_part = "exponent-part";
            Nonterminal sign = "sign";
            Nonterminal real_type_suffix = "real-type-suffix";
            Nonterminal decimal_digits = "decimal-digits";
            Nonterminal decimal_digit = "decimal-digit";

            Expression<CellExpression> Gexpr = "_G";
            Expression<CellExpression> Eexpr = "_E";
            Expression<CellExpression> Eoptexpr = "_E'";
            Expression<CellExpression> Texpr = "_T";
            Expression<CellExpression> Toptexpr = "_T'";
            Expression<CellExpression> Fexpr = "_F";
            Expression<CellExpression> Nexpr = "_N";
            Expression<CellExpression> real_literalexpr = "_real-literal";
            Expression<CellExpression> exponent_partexpr = "_exponent-part";
            Expression<CellExpression> signexpr = "_sign";
            Expression<CellExpression> real_type_suffixexpr = "_real-type-suffix";
            Expression<CellExpression> decimal_digitsexpr = "_decimal-digits";
            Expression<CellExpression> decimal_digitexpr = "_decimal-digit";

            real_literal.Definition = new Rules
            {
                () => sign[true] + decimal_digits[false] + '.' + decimal_digits[false] + exponent_part[true] + real_type_suffix[true],
                () => sign[true] + '.' + decimal_digits[false] + exponent_part[true] + real_type_suffix[true],
                () => sign[true] + decimal_digits[false] + exponent_part[false] + real_type_suffix[true],
                () => sign[true] + decimal_digits[false] + real_type_suffix[true]
            };

            exponent_part.Definition = new Rules
            {
                () => 'e' + sign[true] + decimal_digits[false],
                () => 'E' + sign[true] + decimal_digits[false]
            };

            sign.Definition = new Rules
            {
                () => '+',
                () => '-'
            };

            real_type_suffix.Definition = new Rules
            {
                () => 'F',
                () => 'f'
            };

            decimal_digits.Definition = new Rules
            {
                () => decimal_digit[false] + decimal_digits[true]
            };

            decimal_digit.Definition = new Rules
            {
                () => '0',
                () => '1',
                () => '2',
                () => '3',
                () => '4',
                () => '5',
                () => '6',
                () => '7',
                () => '8',
                () => '9'
            };

            G.Definition = new Rules 
            {
                () => E[false] + Terminal.Null
            };

            Gexpr.Eval = (a, b) => Eexpr[a, b[0]];

            E.Definition = new Rules
            {
                () => T[false] + Eopt[true]
            };

            Eexpr.Eval = (a, b) => Eoptexpr[Texpr[a, b[0]], b[1]];

            T.Definition = new Rules
            {
                () => F[false] + Topt[true]
            };

            Texpr.Eval = (a, b) => Toptexpr[Fexpr[a, b[0]], b[1]];

            F.Definition = new Rules
            {
                () => N[false],
                () => '(' + E[false] + ')'
            };

            Fexpr.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals(N))
                {
                    return Nexpr[a, b[0]];
                }
                if (b[0].Context.Token.Equals('(') && b[1].Context.Token.Equals(E) && b[2].Context.Token.Equals(')'))
                {
                    return Eexpr[a, b[1]];
                }
                throw new NotSupportedException("Input token is not supported");
            };


            N.Definition = new Rules
            {
                () => real_literal[false],
            };

            Nexpr.Eval = (a, b) => real_literalexpr[a, b];

            real_literalexpr.Eval = (a, b) => new Number(b.Context.ToString());

            Eopt.Definition = new Rules
            {
                () => '+' + T[false] + Eopt[true],
                () => '-' + T[false] + Eopt[true]
            };

            Eoptexpr.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals('+'))
                {
                    return Eoptexpr[new Plus(a, Texpr[a, b[1]]), b[2]];
                }
                if (b[0].Context.Token.Equals('-'))
                {
                    return Eoptexpr[new Minus(a, Texpr[a, b[1]]), b[2]];
                }
                throw new NotSupportedException("Input token is not supported");
            };

            Topt.Definition = new Rules
            {
                () => '*' + F[false] + Topt[true],
                () => '/' + F[false] + Topt[true],
            };

            Toptexpr.Eval = (a, b) =>
            {
                if (b[0].Context.Token.Equals('*'))
                {
                    return Toptexpr[new Mul(a, Fexpr[a, b[1]]), b[2]];
                }
                if (b[0].Context.Token.Equals('/'))
                {
                    return Toptexpr[new Div(a, Fexpr[a, b[1]]), b[2]];
                }
                throw new NotSupportedException("Input token is not supported");
            };

            Entity target = G;

            G.Initialize();
            G.Validate();

            Parser input = "6+((7-2)/5-9)*0.5-2+";
            target.Parse(input);

            CellExpression result = Gexpr[input.Tree];

            bool expected = true;
            bool actual = result == null;

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for Parse
        ///</summary>
        [TestMethod(), Conditional("DEBUG")]
        public void Test3_19()
        {
            Terminal asterisk = '*';
            Terminal slash = '/';

            Nonterminal delimited_comment_character = "delimited-comment-character";
            delimited_comment_character.Definition = new Rules
            {
                () => !asterisk,
                () => asterisk + !slash[true],
            };

            Entity target = delimited_comment_character;

            delimited_comment_character.Initialize();
            delimited_comment_character.Validate();

            Parser input = @"*/";
            bool expected = true;
            bool actual;
            actual = target.Parse(input) == false;
            Assert.AreEqual(expected, actual);
        }
    }
}
